package com.skytech.component.crawler.task;

import com.skytech.component.crawler.scratch.base.CrawlerUrl;
import com.skytech.component.crawler.scratch.base.CrawlerUrlDAO;
import com.skytech.component.crawler.scratch.base.CreatePageType;
import com.skytech.component.crawler.scratch.base.TargetRules;
import com.skytech.component.crawler.util.ElementAbstractUrl;
import com.skytech.component.crawler.util.ListRegex;
import org.jsoup.Jsoup;
import org.jsoup.nodes.Document;
import org.jsoup.select.Elements;
import org.openqa.selenium.WebElement;
import org.openqa.selenium.chrome.ChromeDriver;
import org.openqa.selenium.chrome.ChromeOptions;
import org.openqa.selenium.remote.DesiredCapabilities;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.data.domain.Example;
import org.springframework.util.StringUtils;

import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.ArrayList;
import java.util.List;
import java.util.UUID;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicInteger;


public class TaskManager {

    private List<TargetRules> listRules;

    private AtomicInteger index;

    private CrawlerUrlDAO crawlerUrlDAO;

    private int thread = 10;

    private String driverPath;

    private static final Logger log = LoggerFactory.getLogger(TaskManager.class);


    public TaskManager(List<TargetRules> listRules,CrawlerUrlDAO crawlerUrlDAO,String driverPath){
        this.listRules = listRules;
        this.index = new AtomicInteger(listRules.size());
        this.crawlerUrlDAO = crawlerUrlDAO;
        this.driverPath = driverPath;
    }

    private  int next(){
        return index.decrementAndGet();
    }

    public void start(){
        List<Thread> threadList = new ArrayList<>();
        for (int i = 0; i < thread; i++) {
            ConsumerRunnable consumerRunnable = new ConsumerRunnable((name) ->{

                consumer(String.valueOf(name));

            },Integer.toString(i));
            Thread thread = new Thread(consumerRunnable);
            thread.start();
            threadList.add(thread);
        }
        for (Thread task : threadList) {
            try {
                task.join();
            } catch (InterruptedException e) {
                log.error("线程同步失败");
            }
        }
    }

    private void consumer(String name){
        int index = next();
        if(index>=0){
            log.debug("第{}条线程开始",name);
            startRules(listRules.get(index));
            consumer(name);
        }
    }

    private void startRules(TargetRules targetRules){
        DesiredCapabilities capabilities=new DesiredCapabilities();
        ChromeOptions options = new ChromeOptions();
        options.addArguments("--headless");
        options.addArguments("--no-sandbox");
        capabilities.setCapability(ChromeOptions.CAPABILITY, options);
        System.setProperty("webdriver.chrome.driver", driverPath);

        ChromeDriver driver = new ChromeDriver(options);
        try {
            driver.get(targetRules.getSeedUrl());
            driver.manage().timeouts().implicitlyWait(10, TimeUnit.SECONDS);
            partClickNext(driver, targetRules, crawlerUrlDAO,null);
        } catch (Exception e) {
            log.error("{}--超时--{}", targetRules.getId(), e.getMessage());
        }finally {
            driver.quit();
        }
    }



    private void partClickNext(ChromeDriver driver, TargetRules targetRules, CrawlerUrlDAO crawlerUrlDAO,List<String> contentLast) {
        String html = driver.findElementByTagName("html").getAttribute("outerHTML");

        Document parse = Jsoup.parse(html, driver.getCurrentUrl());
        Elements allElements = parse.getAllElements();
        List<String> content = new ArrayList<>();
        if (!StringUtils.isEmpty(targetRules.getContentRegex())) {
            content = ListRegex.regex(ElementAbstractUrl.links(allElements), targetRules.getContentRegex());
        } else if (!StringUtils.isEmpty(targetRules.getContentElement())) {
            Elements elements = allElements.select(targetRules.getContentElement());
            if (!elements.isEmpty()) {
                content = ElementAbstractUrl.links(elements.get(0).getAllElements());
            }
        } else {
            return;
        }
        CrawlerUrl crawlerUrl = new CrawlerUrl();
        int i = 0;
        for (String contentUrl : content) {
            i++;
            crawlerUrl.setContentUrl(contentUrl);
            if (!crawlerUrlDAO.findAll(Example.of(crawlerUrl)).isEmpty()) {
                continue;
            }
            CrawlerUrl c = new CrawlerUrl();
            c.setId(UUID.randomUUID().toString());
            c.setContentUrl(contentUrl);
            c.setDomainUrl(driver.getCurrentUrl());
            c.setRuleId(targetRules.getId());
            c.setParse("no");
            c.setOperateTime(LocalDateTime.now().format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss")));
            crawlerUrlDAO.save(c);
        }
        String currentPath = driver.getCurrentUrl();
        try {
            if (StringUtils.isEmpty(targetRules.getNextButton())) {
                log.debug("{}-没有配置翻页", targetRules.getNextButton());
                return;
            }

            WebElement element = driver.findElementByXPath(targetRules.getNextButton());

            log.info("按钮连接{}", element.getAttribute("href"));
            log.info("当前页面{}", driver.getCurrentUrl());
            if (!CreatePageType.url_unchanged.toString().equals(targetRules.getType()) && driver.getCurrentUrl().equals(element.getAttribute("href"))) {
                //如果两次点击的页面相同停止当前任务
                log.error("{}两次链接地址相同,当前页{}，下一页{}", targetRules.getId(), driver.getCurrentUrl(), element.getAttribute("href"));
                return;
            }
            if (CreatePageType.url_unchanged.toString().equals(targetRules.getType())) {
                if (contentLast != null && content.size() != 0) {
                    if (contentLast.equals(content)) {
                        log.error("{}两次链接内容相同,当前页{}，下一页{}", targetRules.getId(), driver.getCurrentUrl(), element.getAttribute("href"));
                        return;
                    }
                }
                contentLast = content;
            }
            element.click();
            if(CreatePageType.url_unchanged.toString().equals(targetRules.getType())){
                Thread.sleep(3000);
            }
        } catch (Exception e) {
            log.error("{}点击下一页出现问题{}", targetRules.getId(), e.getMessage());
            return;
        }
        driver.manage().timeouts().implicitlyWait(10, TimeUnit.SECONDS);
        String nextPath = driver.getCurrentUrl();
        if (!CreatePageType.url_unchanged.toString().equals(targetRules.getType()) && currentPath.equals(nextPath)) {
            //点击
            log.error("{}点击方法,当前页{}，下一页{}", targetRules.getId(), currentPath, nextPath);
            return;
        }


        partClickNext(driver, targetRules, crawlerUrlDAO,contentLast);

    }
    public List<TargetRules> getListRules() {
        return listRules;
    }

}
